package streamforce.workload.test;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Properties;

import streamforce.crypto.event.StockEvent;
import streamforce.crypto.message.CloseConnection;
import streamforce.crypto.message.DumpStat;

/**
 * Read data from files and send with specified rate. 
 * This is used for with encrypted files using Agg-2
 */
public class DataSender {
	int startStreamIdx, nFiles; 
	ArrayList<StreamManager> sm;
	int rate; 
	int currentIdx; 
	int max; 	
	public DataSender(int nFiles, int startStreamIdx, int startFileIdx, int rate, int max) throws Exception{
		this.startStreamIdx = startStreamIdx;
		this.sm = new ArrayList<StreamManager>(); 
		this.nFiles = nFiles;
		this.rate = rate;
		this.currentIdx = 0; 
		this.max = max; 
		
		for (int i=0; i<nFiles; i++){
			sm.add(new StreamManager(i+this.startStreamIdx, startFileIdx)); 
		}
	}
	
	public DataSender(String fileName) throws Exception {
		BufferedReader reader = new BufferedReader(new FileReader(fileName));
		this.nFiles = new Integer(reader.readLine()).intValue();
		this.startStreamIdx = new Integer(reader.readLine()).intValue();
		int startFileIdx = new Integer(reader.readLine()).intValue();
		this.rate = new Integer(reader.readLine()).intValue();
		this.max = new Integer(reader.readLine()).intValue();
		this.currentIdx = 0;
		for (int i = 0; i < this.nFiles; i++) {
			sm.add(new StreamManager(new Integer(reader.readLine()).intValue(),
					startFileIdx));
		}
	}
	
	public void send(ObjectOutputStream oos) throws Exception{
		long start, end;
		int count=0; 
		do{
			start = System.currentTimeMillis(); 
			for (int i=0; i<this.rate; i++){
				oos.writeObject(this.getNextEvent());
				count++; 
			}
			oos.flush(); 
			end = System.currentTimeMillis(); 
			if ((end-start)<1000)
				Thread.sleep(1000-(end-start));
			
		}
		while (count<this.max); 
		oos.writeObject(new DumpStat()); 
		Thread.sleep(5000); 
		//oos.writeObject(new CloseConnection()); 		 
	}
	
	private StockEvent getNextEvent() throws Exception{
		StockEvent se = this.sm.get(this.currentIdx).getNextEvent(); 
		this.currentIdx = (this.currentIdx+1)%this.nFiles;
		return se; 
	}
	
	//<nFiles> <startIdx> <startFileIdx> <rate> <max> 
	public static void main(String[] args) throws Exception{
		DataSender ds; 
		if (args.length == 1) {
			ds = new DataSender(args[0]);
		} else {
			int nFiles = new Integer(args[0]).intValue();
			int startIdx = new Integer(args[1]).intValue();
			int fileIdx = new Integer(args[2]).intValue();
			int rate = new Integer(args[3]).intValue();
			int max = new Integer(args[4]).intValue();
			ds = new DataSender(nFiles, startIdx, fileIdx, rate, max);
		}
		
		ObjectOutputStream oos;		
		Properties property = new Properties();
		
		property.load(new FileInputStream("attributes.properties"));
		int port = new Integer(property.getProperty("serverPort")).intValue();
		Socket clientSocket = new Socket(property.getProperty("serverHost"),
				port);
		oos = new ObjectOutputStream(clientSocket.getOutputStream());
		System.out.println("Connected ."); 
		ds.send(oos); 
		
	}
}
